﻿#include "RXTree.h"

BeginMetaData(RXTree)

META_DefaultConstructor

META_BEGIN_PROPERTY(Name)
META_ADD_GETTER(GetName)
META_ADD_SETTER(SetName)
META_END_PROPERTY


META_BEGIN_PROPERTY(Parent)
META_ADD_GETTER(GetParent)
META_ADD_SETTER(SetParent)
META_ADD_NOTIFIER(ParentChanged)
META_END_PROPERTY

META_BEGIN_SIGNAL(ParentChanged)
META_END_SIGNAL

EndMetaData

RXTree::RXTree()
{
	m_parent = NULL;
}

RXTree::~RXTree()
{
	swapParent(NULL);
	auto child = m_children;

	for (auto &i : child) {
		delete i;
	}
}

std::vector<RXTree*> RXTree::GetChildren()
{
	return { m_children.begin(),m_children.end() };
}

void RXTree::SetParent(RXTree * child)
{
	if (thread() != std::this_thread::get_id() || (child && child->thread() != std::this_thread::get_id())) {
		std::cerr << "SetParent Failed,Cannot Set Parent In Another Thread!" << std::endl;
		return;
	}

	if (m_parent == child) {
		return;
	}

	if (IsAncestorOf(child)) {
		std::cerr << "SetParent Failed,Loop Detected!" << std::endl;
		return;
	}

	swapParent(child);
	ParentChanged();
}

RXTree * RXTree::GetParent() const
{
	return m_parent;
}

bool RXTree::IsAncestorOf(RXTree * child)
{
	if (child == this) {
		return false;
	}

	auto p = child->m_parent;

	while (true)
	{
		if (p == this) {
			return true;
		}

		if (!p) {
			return false;
		}

		p = p->m_parent;
	}

	return false;
}

std::wstring RXTree::GetName() const
{
	return m_name;
}

void RXTree::SetName(std::wstring name)
{
	m_name = name;
}

void RXTree::FindChildImp(const MetaInfo & meta, const std::wstring & name, bool isAll, bool isRecursive, std::vector<RXTree*>& ret) const
{
	
	for (auto &i : m_children) {
		if (i->GetMetaInfo() == meta || meta.IsBaseOf(i->GetMetaInfo())) {
			if (name.empty() || name == i->GetName()) {
				ret.push_back(i);
			}
		}

		if (isRecursive) {
			i->FindChildImp(meta,name,isAll,isRecursive,ret);
		}
	}
}

void RXTree::swapParent(RXTree * p)
{
	if (m_parent) {
		m_parent->m_children.erase(this);
	}
	m_parent = p;
	if (m_parent) {
		m_parent->m_children.insert(this);
	}
}
